package com.hao.nettyrpc.transport.netty.server;

import com.hao.nettyrpc.entity.RpcRequest;
import com.hao.nettyrpc.entity.RpcResponse;
import com.hao.nettyrpc.factory.SingletonFactory;
import com.hao.nettyrpc.handle.RequestHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutorService;

/**
 * @author haoge
 * @version 1.0
 * @date 2023/4/11 13:48
 */
public class NettyServerHandle extends SimpleChannelInboundHandler<RpcRequest> {
    private static final Logger logger = LoggerFactory.getLogger(NettyServerHandle.class);
    private final RequestHandler requestHandler;


    public NettyServerHandle() {
        this.requestHandler = SingletonFactory.getInstance(RequestHandler.class);
    }


    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, RpcRequest rpcRequest) throws Exception {

        try {
            if (rpcRequest.getHeartBeat()) {
                logger.info("接收到客户端心跳包...");
                return;
            }
            logger.info("服务器接收到请求: {}", rpcRequest);
            Object result = requestHandler.handle(rpcRequest);
            if (channelHandlerContext.channel().isActive() && channelHandlerContext.channel().isWritable()) {
                channelHandlerContext.writeAndFlush(RpcResponse.success(result, rpcRequest.getRequestId()));
            } else {
                logger.error("通道不可写");
            }
        } finally {
            ReferenceCountUtil.release(rpcRequest);
        }
    }



    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.error("处理过程调用时有错误发生:");
        cause.printStackTrace();
        ctx.close();
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleState state = ((IdleStateEvent) evt).state();
            if (state == IdleState.READER_IDLE) {
                logger.info("长时间未收到心跳包，断开连接...");
                ctx.close();
            }
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }
}
